#include "QDivaWindow.h"
#include "DIVA_Application.h"
#include "QDivaWindowController.h"
#include "DIVA_Qt/QDivaCtrlPanel/QDivaCtrlPanel.h"
#include "QDivaAppController.h"
#include "QLogger.h"
#include "QOgreStats.h"
#include "DIVA_Qt/MDSManagerDialog.h"
#include "MappingEngine.h"
#include "vm/DIVA_VM.h"
#include "explorebot/ExplorBotMangerDialog.h"
#include "explorebot/ExplorBotLibrary.h"
#include "layout/LayoutLibrary.h"
#include "explorebot/QExploreBotStats.h"
#include <QSize>
#include <QFile>
#include <QToolButton>
#include <QDockWidget>
#include <QAction>

#define PATH_CONTINUE_ICON ":/resource/diva_icon/continue.png"
#define PATH_NEXT_ICON ":/resource/diva_icon/step_over.png"
#define PATH_STEP_ICON ":/resource/diva_icon/step_into.png"
#define PATH_CHANGE_BACKGROUND_ICON ":/resource/diva_icon/change_background.png"
#define PATH_ANIMATION_ICON ":/resource/diva_icon/animation.png"
#define PATH_LAYOUT_ICON "images/diva_icon/layout.png"
#define PATH_NEW_VM_ICON ":/resource/diva_icon/new_vm.png"

#define PATH_UP_ICON ":/resource/diva_icon/up.png"
#define PATH_LEFT_ICON ":/resource/diva_icon/left.png"
#define PATH_DOWN_ICON ":/resource/diva_icon/down.png"
#define PATH_RIGHT_ICON ":/resource/diva_icon/right.png"
#define PATH_ZOOM_IN_ICON ":/resource/diva_icon/zoom_in.png"
#define PATH_ZOOM_OUT_ICON ":/resource/diva_icon/zoom_out.png"

QDivaWindow::QDivaWindow(QWidget *parent)
	: QMainWindow(parent)
{
	ui.setupUi(this);
	setStyle();
	init();
	setUpDebuggerActions();
	setUpDivaAppActions();
	setUpCameraActions();
	setUpToolBar();
	connectSlots();
}

QDivaWindow::~QDivaWindow()
{

}

//private, should be called after setUpToolBarActions() and setUpToolBar().
void QDivaWindow::connectSlots(){
	QDivaWindowController *handler = QDivaWindowController::getInstance();
	QDivaAppController *col = DIVA_Application::getInstance()->getController();

	connect( _divaAppActions[LAYOUT], SIGNAL( triggered() ), 
		handler, SLOT( doLayout() ) );	
	connect( _divaAppActions[ANIMATION], SIGNAL( triggered() ), 
		handler, SLOT( doAnimation() ) );	
	connect( _debuggerActions[CONTINUE], SIGNAL( triggered() ), 
		handler, SLOT( doContinue() ) );
	connect( _divaAppActions[NEW_VM], SIGNAL( triggered() ), 
		handler, SLOT( doNewVM() ) );

	connect( _divaAppActions[CHANGE_BACKGROUND], SIGNAL( triggered() ), 
		handler, SLOT( doChangeBackground() ) );
	connect( _debuggerActions[NEXT], SIGNAL( triggered() ), 
		handler, SLOT( doNext() ) );
	connect( _debuggerActions[STEP], SIGNAL( triggered() ), 
		handler, SLOT( doStep() ) );

	connect( col, SIGNAL( rightClicked(DIVA_VM*) ), 
		this, SLOT( rightClickMenu(DIVA_VM*) ) );

}

// private, should be called inside constructor.
void QDivaWindow::init()
{


	QLogger *logger = QLogger::getInstance();
	_loggerWindow = new QAction("Logger",ui.menuWindow );
	_loggerWindow->setCheckable(true);
	_loggerWindow->setChecked(true);
	ui.menuWindow->addAction(_loggerWindow);
	logger->setParent(this);

 	QOgreStats *stat = QOgreStats::getInstance();
	_statWindow = new QAction("Ogre Stat",ui.menuWindow );
	_statWindow->setCheckable(true);
	_statWindow->setChecked(true);
	ui.menuWindow->addAction(_statWindow);
 	stat->setParent(this);

	QExploreBotStats* Qebs = QExploreBotStats::getInstance();
	_ExplorestatWindow = new QAction("ExploreBotStats",ui.menuWindow );
	_ExplorestatWindow->setCheckable(true);
	_ExplorestatWindow->setChecked(true);
	ui.menuWindow->addAction(_ExplorestatWindow);
	Qebs->setParent(this);

	QDockWidget *statDock = new QDockWidget("Ogre Stats", this);
	statDock->setWidget(stat);
	statDock->setAllowedAreas(Qt::BottomDockWidgetArea);
	statDock->setObjectName("stat");
	this->addDockWidget(Qt::BottomDockWidgetArea, statDock);
	statDock->adjustSize();
	connect( statDock, SIGNAL(visibilityChanged(bool)), this, SLOT(showStatWindow()));

	QDockWidget *loggerDock = new QDockWidget("Log", this);
	loggerDock->setWidget(logger);
	loggerDock->setAllowedAreas(Qt::BottomDockWidgetArea);
	loggerDock->setObjectName("logger");
	loggerDock->adjustSize();
	this->addDockWidget(Qt::BottomDockWidgetArea, loggerDock);
	connect( loggerDock, SIGNAL(visibilityChanged(bool)), this, SLOT(showLoggerWindow()));

	QDockWidget *ExploreBotStatsDock = new QDockWidget("ExploreBot Stats", this);
	ExploreBotStatsDock->setWidget(Qebs);
	ExploreBotStatsDock->setAllowedAreas(Qt::BottomDockWidgetArea);
	ExploreBotStatsDock->setObjectName("EBS");
	this->addDockWidget(Qt::BottomDockWidgetArea, ExploreBotStatsDock);
	ExploreBotStatsDock->adjustSize();
	connect( statDock, SIGNAL(visibilityChanged(bool)), this, SLOT(showExplorebotsWindow()));

	connect(ui.actionManager, SIGNAL(triggered()), this ,SLOT(popMDSManagerDialog()));
	connect(ui.actionExplorBotManger, SIGNAL(triggered()),this,SLOT(popExplorBotMangerDialog()));
	connect( _loggerWindow, SIGNAL(triggered()), this, SLOT(showLoggerWindow()));
	connect( _statWindow, SIGNAL(triggered()), this, SLOT(showStatWindow()));

	DIVA_Application* divaApp = DIVA_Application::getInstance();
	divaApp->setParent( this );
	this->setCentralWidget(divaApp);
	divaApp->go();
	//ExplorBotLibrary::getInstance();
	LayoutLibrary::getInstance();
}

// private, should be called before calling setUpToolBar().
void QDivaWindow::setUpDebuggerActions(){
	// operator[] won't work since it will cause
	// IndexOutOfBounds exception.	
	_debuggerActions.insert( CONTINUE, 
		new QAction( QIcon(PATH_CONTINUE_ICON), "Continue", this) );	
	_debuggerActions.insert( NEXT, 
		new QAction( QIcon(PATH_NEXT_ICON), "Step Over", this) );
	_debuggerActions.insert( STEP, 
		new QAction( QIcon(PATH_STEP_ICON), "Step Into", this) );
}


void QDivaWindow::setUpDivaAppActions(){
	_divaAppActions.insert( LAYOUT, 
		new QAction( QIcon(PATH_LAYOUT_ICON), "Layout", this) );
	_divaAppActions.insert( ANIMATION, 
		new QAction( QIcon(PATH_ANIMATION_ICON), "Animation", this) );
	_divaAppActions.insert( CHANGE_BACKGROUND, 
		new QAction( QIcon(PATH_CHANGE_BACKGROUND_ICON), "Change Background", this) );
	_divaAppActions.insert( NEW_VM, 
		new QAction( QIcon(PATH_NEW_VM_ICON), "Create new composite VM", this) );
}

void QDivaWindow::setUpCameraActions()
{
	_cameraActions.insert( UP, 
		new QAction(QIcon(PATH_UP_ICON), "up", this) );
	_cameraActions.insert(LEFT,
		new QAction(QIcon(PATH_LEFT_ICON), "left", this) );
	_cameraActions.insert(DOWN,
		new QAction(QIcon(PATH_DOWN_ICON), "down", this) );
	_cameraActions.insert(RIGHT,
		new QAction(QIcon(PATH_RIGHT_ICON), "right", this) );
	_cameraActions.insert(ZOOM_IN,
		new QAction(QIcon(PATH_ZOOM_IN_ICON), "zoom in", this) );
	_cameraActions.insert(ZOOM_OUT,
		new QAction(QIcon(PATH_ZOOM_OUT_ICON), "zoom out", this) );
}



// private, should be called after calling setUpToolBarActions().
void QDivaWindow::setUpToolBar(){
	this->removeToolBar(ui.mainToolBar);

	QToolBar* debuggerToolBar = new QToolBar(this);
	debuggerToolBar->setOrientation(Qt::Vertical);
	debuggerToolBar->setWindowTitle("Debugging Tools");
	debuggerToolBar->addActions( _debuggerActions.values() );
	debuggerToolBar->setIconSize(QSize(24,24));
	debuggerToolBar->setToolButtonStyle(Qt::ToolButtonIconOnly);
	this->addToolBar(Qt::LeftToolBarArea, debuggerToolBar);

	QToolBar* divaAppToolBar = new QToolBar(this);
	divaAppToolBar->setOrientation(Qt::Vertical);
	divaAppToolBar->setWindowTitle("DIVA Application Tools");
	divaAppToolBar->addActions( _divaAppActions.values() );
	divaAppToolBar->setToolButtonStyle(Qt::ToolButtonIconOnly);
	this->addToolBar(Qt::LeftToolBarArea, divaAppToolBar);
	divaAppToolBar->setIconSize(QSize(24,24));

 	QToolBar* cameraToolBar = new QDivaCtrlPanel(this);
	cameraToolBar->setOrientation(Qt::Vertical);
	cameraToolBar->setWindowTitle("Camera Action Tools");
 	this->addToolBar(Qt::LeftToolBarArea, cameraToolBar);
}

// private
void QDivaWindow::setStyle()
{
	QFile* cssFile = new QFile(":/resource/diva_style.css");
	assert(cssFile);
	cssFile->open(QFile::ReadOnly);
	QByteArray css = cssFile->readAll();
	this->setStyleSheet(css);
	cssFile->close();
	delete cssFile;
}

void QDivaWindow::popMDSManagerDialog()
{
	MDSManagerDialog *dialog = new MDSManagerDialog(this);
	dialog->setAttribute(Qt::WA_DeleteOnClose);
	int result = dialog->exec();

	MappingEngine::getInstance()->reloadMDSfiles();
}

void QDivaWindow::popExplorBotMangerDialog()
{
	ExplorBotMangerDialog *dialog = new ExplorBotMangerDialog(this);
	dialog->setAttribute(Qt::WA_DeleteOnClose);
	int result = dialog->exec();

	//MappingEngine::getInstance()->reloadMDSfiles();
}

void QDivaWindow::showLoggerWindow()
{
	bool isCheck;
	QDockWidget *logger = findChild<QDockWidget*>("logger");

	if ( QObject::sender()->objectName() == "logger" ){
		isCheck = logger->isVisible();
	} else {
		isCheck = _loggerWindow->isChecked();
	}

	_loggerWindow->setChecked(isCheck);

	
	logger->setVisible(isCheck);
}

void QDivaWindow::showExplorebotsWindow(){
	bool isCheck;
	QDockWidget *stat = findChild<QDockWidget*>("EBS");

	if ( QObject::sender()->objectName() == "EBS" ){
		isCheck = stat->isVisible();
	} else {
		isCheck = _statWindow->isChecked();
	}
	_statWindow->setChecked(isCheck);


	stat->setVisible(isCheck);
}

void QDivaWindow::showStatWindow()
{
	bool isCheck;
	QDockWidget *stat = findChild<QDockWidget*>("stat");

	if ( QObject::sender()->objectName() == "stat" ){
		isCheck = stat->isVisible();
	} else {
		isCheck = _statWindow->isChecked();
	}
	_statWindow->setChecked(isCheck);

	
	stat->setVisible(isCheck);
}

void QDivaWindow::rightClickMenu(DIVA_VM* vm)
{
	QDivaWindowController *handler = QDivaWindowController::getInstance();
	QMenu* contextMenu = new QMenu ( this );
	Q_CHECK_PTR ( contextMenu );
	contextMenu->addAction ( "Add New ExplorBot" , handler , SLOT (addExplorBot()));
	contextMenu->addAction ( "Add New Layout" , handler , SLOT (doLayout()));
	contextMenu->popup( QCursor::pos() );
	contextMenu->exec ();
	delete contextMenu;
	contextMenu = 0;
}

